class Preview {
  constructor() {
    this.videoCanvas = document.createElement('canvas');
    this.videoContext = this.videoCanvas.getContext('2d');
    this.iconMap = {
      folder: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>`,
      file: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>`,
      audio: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18V5l12-2v13"></path><circle cx="6" cy="18" r="3"></circle><circle cx="18" cy="16" r="3"></circle></svg>`,
      video: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="2" width="20" height="20" rx="2.18" ry="2.18"></rect><line x1="7" y1="2" x2="7" y2="22"></line><line x1="17" y1="2" x2="17" y2="22"></line><line x1="2" y1="12" x2="22" y2="12"></line><line x1="2" y1="7" x2="7" y2="7"></line><line x1="2" y1="17" x2="7" y2="17"></line><line x1="17" y1="17" x2="22" y2="17"></line><line x1="17" y1="7" x2="22" y2="7"></line></svg>`,
      compressed: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path><polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline><line x1="12" y1="22.08" x2="12" y2="12"></line></svg>`,
      executable: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="4" y="4" width="16" height="16" rx="2" ry="2"></rect><rect x="9" y="9" width="6" height="6"></rect><line x1="9" y1="1" x2="9" y2="4"></line><line x1="15" y1="1" x2="15" y2="4"></line><line x1="9" y1="20" x2="9" y2="23"></line><line x1="15" y1="20" x2="15" y2="23"></line><line x1="20" y1="9" x2="23" y2="9"></line><line x1="20" y1="14" x2="23" y2="14"></line><line x1="1" y1="9" x2="4" y2="9"></line><line x1="1" y1="14" x2="4" y2="14"></line></svg>`
    };
    this.typeMap = {
      image: new Set(['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico']),
      video: new Set(['mp4', 'webm', 'mkv', 'mov', 'avi']),
      audio: new Set(['mp3', 'wav', 'flac', 'ogg']),
      compressed: new Set(['zip', 'rar', '7z', 'tar', 'gz', 'bz2']),
      executable: new Set(['exe', 'msi', 'bat', 'sh', 'cmd'])
    };
    // Helper for backward compatibility or direct access if needed
    this.imageTypes = this.typeMap.image;
    this.videoTypes = this.typeMap.video;
    this.audioTypes = this.typeMap.audio;
  }

  isImage(ext) {
    return this.imageTypes.has(ext.toLowerCase());
  }

  isVideo(ext) {
    return this.videoTypes.has(ext.toLowerCase());
  }

  isAudio(ext) {
    return this.audioTypes.has(ext.toLowerCase());
  }

  getFileExtension(filename) {
    return filename.split('.').pop();
  }

  getFileType(ext) {
    ext = ext.toLowerCase();
    for (const [type, set] of Object.entries(this.typeMap)) {
      if (set.has(ext)) return type;
    }
    return 'file';
  }

  async generateThumbnail(file) {
    const ext = this.getFileExtension(file.file);
    let content;
    let className = 'preview-thumbnail';

    if (file.fileType === '/') {
      content = this.iconMap.folder;
      className += ' is-folder';
      return el('div', { class: className }, content);
    }

    const type = this.getFileType(ext);

    if (type === 'image') {
      content = el('img', { src: file.filePath, loading: 'lazy', alt: file.file });
    } else if (type === 'video') {
      try {
        const thumbnail = await this.createVideoThumbnail(file.filePath);
        const playOverlay = el('div', {
          class: 'play-overlay', onclick: (e) => {
            if (this.isVideo(ext)) {
              e.preventDefault();
              e.stopPropagation();
              playVideo(file.filePath);
            }
          }
        }, playPauseBtnHTML);
        const container = el('div', { class: className }, [thumbnail, playOverlay]);
        return container;
      } catch (e) {
        console.error('Failed to generate video thumbnail', e);
        content = this.iconMap.video;
        className += ' is-icon';
      }
    } else if (type === 'audio') {
      content = this.iconMap.audio;
      className += ' is-icon';
      // Add play button for audio
      const playBtnContainer = el('div', {
        class: 'play-overlay',
        'data-filepath': file.filePath,
        'data-type': this.getFileExtension(file.file),
        onclick: (e) => {
          e.stopPropagation();
          e.preventDefault();
          if (this.onPlayAudio) {
            this.onPlayAudio(e.currentTarget, file.filePath);
          }
        }
      }, playPauseBtnHTML);

      if (this.onInitAudioButton) {
        const btn = playBtnContainer.querySelector('.play_pause_btn');
        this.onInitAudioButton(btn, file.filePath);
      }

      return el('div', { class: className }, [content, playBtnContainer]);
    } else if (this.iconMap[type]) {
      content = this.iconMap[type];
      className += ' is-icon';
    } else {
      content = this.iconMap.file;
      className += ' is-icon';
    }

    return el('div', { class: className }, content);
  }

  createVideoThumbnail(url) {
    return new Promise((resolve, reject) => {
      const video = document.createElement('video');
      video.crossOrigin = 'anonymous';
      video.preload = "metadata";
      video.src = url;
      video.muted = true;

      video.onloadedmetadata = () => {
        video.currentTime = 1;
      };

      video.onseeked = () => {
        try {
          this.videoCanvas.width = video.videoWidth;
          this.videoCanvas.height = video.videoHeight;
          this.videoContext.drawImage(video, 0, 0);

          resolve(el('img', {
            src: this.videoCanvas.toDataURL('image/jpeg')
          }));

        } catch (err) {
          reject(err);
        } finally {
          video.remove();
        }
      };

      video.onerror = reject;
    });
  }

  renderGrid(files, container) {
    container.innerHTML = '';
    container.className = 'file-list grid-view';

    if (files.length === 0) {
      container.appendChild(el('p', { style: 'text-align:center; color:#555; padding: 20px; width: 100%;' }, '当前目录为空'));
      return;
    }

    const fragment = document.createDocumentFragment();

    files.forEach(file => {
      const thumbContainer = el('div', { class: 'grid-thumb-container' });

      this.generateThumbnail(file).then(thumb => {
        thumbContainer.appendChild(thumb);
      });

      const name = el('div', { class: 'grid-name' }, file.file);

      const children = [thumbContainer, name];

      if (file.fileType !== '/') {
        const delBtn = el('button', {
          class: 'grid-del-btn',
          onclick: (e) => {
            e.stopPropagation();
            handleDelete(file.filePath);
          }
        }, '×'); // Using simple x char or could use HTML entity if el supports it well
        children.push(delBtn);
      }

      const item = el('div', {
        class: 'grid-item',
        title: file.file,
        onclick: (e) => {
          if (e.target.closest('.grid-del-btn')) return;

          if (file.fileType === '/') {
            location.href = file.filePath;
          } else {
            location.href = file.filePath;
          }
        }
      }, children);

      fragment.appendChild(item);
    });

    container.appendChild(fragment);
  }
}
